// CECompactForeverShell.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include "DebugZones.h"

// Define the shell name (without .exe) here (You can override on the commandline):
#define SHELL_NAME  L"CECompactMinShell"
#define WINDOWS_PATH L"\\Windows\\"

BOOL FileExists(LPCWSTR pszFilename);

//Command line: Comapct13ForeverShell   [<shell app to run>]
int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
	RETAILREGISTERZONES(NULL);

	FUNC_ENTRY(L"argc=%d, argv*=0x%08X, envp*=0x%08X", argc, argv, envp);

	// Default shell name
	LPWSTR pszShellName = SHELL_NAME;
	LPWSTR pszParams = NULL;

	// Default shell full path
	WCHAR szExeName[MAX_PATH] = WINDOWS_PATH SHELL_NAME L".exe";

	//Get the shell app from the command line if given, and chack that it exists
	if (argc > 1)
	{   // Construct full path and see if the file exists
		WCHAR szTemp[MAX_PATH];
		wcscpy_s(szTemp, _countof(szTemp), WINDOWS_PATH);
		wcscat_s(szTemp, _countof(szTemp), argv[1]);
		wcscat_s(szTemp, _countof(szTemp), L".exe");
		if (FileExists(szTemp))
		{   // Found so use the command line specified app for the shell
			wcscpy_s(szExeName, _countof(szExeName), szTemp);
			pszShellName = argv[1];
		}
		else
		{   // Otherwise probably a Depends value (from registry, wrt startup order),
			// So Pass Depends parameter to actual shell so it can signal dependenat apps
			pszParams = argv[1];
		}
	}

	// Assume success
	DWORD dwReturn = ERROR_SUCCESS;
	PROCESS_INFORMATION pi = { NULL };

	//Loop forever. When CECompactMinShell exits, ie restart it
	for (int i = 1;; i++)
	{
		// As an example; take note that you can concatenate L"" strings like this:
		LOGMSG(ZONE_INFO, L"INFO: The shell %s is being launched by CECompactForeverShell.\r\n", pszShellName);

		//Launch Shell app as a separate process
		if (!CreateProcess(szExeName, pszParams, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi))
		{
			dwReturn = GetLastError();
			LOGMSG(ZONE_ERROR, L"ERROR: %s failed to be launched by CECompactForeverShell, error %d. Launch no.: %d. Exiting.\r\n", dwReturn, szExeName, i);
			break;
		}
		// No need for thread handle, so close it
		CloseHandle(pi.hThread);

		LOGMSG(ZONE_INFO, L"INFO: %s launched by CECompactForeverShell. Launch no.: %d", pszShellName, i);

		//Wait for it to exit
		if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE))
		{
			CloseHandle(pi.hProcess);
			pi.hProcess = NULL;
		}
		else
		{
			dwReturn = GetLastError();
			break;
		}
		LOGMSG(ZONE_INFO, L"INFO: %s has closed. CECompactForeverShell app will attempt to relaunch it automatically.", pszShellName);
	}
	// Clean up
	if (pi.hProcess)
		CloseHandle(pi.hProcess);

	FUNC_EXIT(L"%d", dwReturn);
	return dwReturn;
}

// Returns true if the file (full path required) exists
BOOL FileExists(LPCWSTR pszFilename)
{
	FUNC_ENTRY(L"Filename=%s", pszFilename);
	WIN32_FIND_DATA fd;
	HANDLE hFind = FindFirstFile(pszFilename, &fd);
	FindClose(hFind);
	BOOL bReturn = ((INVALID_HANDLE_VALUE != hFind) && (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)));
	FUNC_EXIT(L"%s", bReturn ? "true" : "false");
	return bReturn;
}

